package mac10.models;

import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import mac10.monitor.InfoMonitor;
import mac10.roles.AbstractRole;
import mac10.util.SimpleCluster;


public class ClusterBook
{
    public static ClusterBook staticClusterBook = new ClusterBook();
    private  SimpleCluster simpleCluster = new SimpleCluster(WorldModel.staticWorldModel);
    
    private HashMap<String, Cluster> book = new HashMap<String, Cluster>();
    
    public HashMap<String, Cluster> getBook ()
    {
        return book;
    }

    int counter = 0;
    
    public Cluster getCluster(String hash)
    {
        return book.get(hash);
    }
    

    
    public void update()
    {        
        ArrayList<Cell> cows = WorldModel.staticWorldModel.getCowsAsCellList();
        HashMap<String, Cluster> newBook = new HashMap<String, Cluster>();
        
        
        for (String hash : book.keySet())
        {
            Cluster cluster =  book.get(hash);
            cluster.updatePostions();
            
            if(cluster.getList().size() <1)
                continue;
            
            Cell centerCow = cluster.getNearstCowToDensityCenter();
            
            if(centerCow == null )
            {
                continue;
            }
            Color clusterColor = cluster.clusterColor;
            cluster = simpleCluster.newCluster(centerCow);       
            cluster.setClusterColor(clusterColor);
            cluster.setId(hash);

            
            if(cluster.size() < 1)
                continue;
            
            //sind zwei cluster gejoint?
            Cluster oldCluster = clusterAlreadyinBook(newBook, cluster);
            if( oldCluster != null )
            {               
                //wenn oldcluster for dem joinen grösser war
                if(book.get( oldCluster.getId() ).size() > book.get( cluster.getId() ).size() )
                    continue;
                else
                    newBook.remove(oldCluster.getId());
            }
                
            cows.removeAll(cluster.getList());
            newBook.put(hash, cluster);           
        }
        ArrayList<Cluster> currentCluster = simpleCluster.getClusters(cows);

        Random generator = new Random();
        for (Cluster cluster : currentCluster)
        {
            if(cluster.size() < 1)
                continue;
            
            String hash = generateHash(cluster);           
            newBook.put(hash, cluster);   
            cluster.setId(hash);
            cluster.setClusterColor(new Color(generator.nextInt(100), generator.nextInt(255), generator.nextInt(100)));            
        }
        book = newBook;        
        
        System.out.println("\tClusters=" + newBook.size());

        ArrayList<String> deleteCluster = new ArrayList<String>();
        
        for (Cluster cluster:book.values()) {
        	if(cluster.size() < 1) {
        		deleteCluster.add(cluster.getId());
        		continue;
        	}
        	
        	cluster.calculateSmoothValue();
            System.out.println("\t\tCluster " + cluster.getId() + " smooth=" + cluster.smoothValue + " size=" + cluster.getList().size());
            cluster.assurePath(WorldModel.staticWorldModel, System.currentTimeMillis() + 20);
            if (cluster.getStart() != null) {
            	cluster.pathToCorral = AbstractRole.nodeToActionStrings(cluster.getStart());
            } else {
            	cluster.pathToCorral = null;
            }
        }
        
        for (String key:deleteCluster) {
        	book.remove(key);
        }
        
    }

    private Cluster clusterAlreadyinBook (HashMap<String, Cluster> newBook,
            Cluster cluster)
    {
        for (Cluster oldCluster : newBook.values())
        {
            if(compareCluster(cluster, oldCluster)  == 1)
                return oldCluster;
        }
        return null;
    }



    private String generateHash (Cluster cluster)
    {
        counter++;
        return "c" + counter; 
    }


    private double compareCluster (Cluster cluster, Cluster oldCluster)
    {
        int n = oldCluster.getList().size();
        
        if (Math.abs(cluster.getList().size() - n) > (n / 2))
        {
            return 0;
        }
        
        ArrayList<Integer> oldList = oldCluster.getIdList();
        ArrayList<Integer> newList = cluster.getIdList();
        double c = 0;
        
        for (Integer id : newList)
        {
            if(oldList.contains(id))
                c++;
        }
//        System.out.println("Compare "+cluster + " || "+ oldCluster + " = " + c + "//" + n + " _ " + c/n);
        return c/n;
    }
    
    public void clusterDebug()
    {

        
        for (String hash : book.keySet())
        {
            
            String s = hash;
            
            for (Cell cell : book.get(hash).getList())
            {
                s+=cell.toStringShort();
            }
            InfoMonitor.staticMonitor.addLineToRightText(s+"\n");
        }
        
    }
    
}
